package cuShapes;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;

import javax.xml.bind.annotation.XmlTransient;

import palette.CanvasManager;
import palette.CanvasWindow;

@SuppressWarnings("serial")
@XmlTransient
public class ShapeList extends LinkedList<PQShape>{
	
	@XmlTransient
	private PQShape currentShape;
	
	@XmlTransient
	transient private LinkedList<ShapeListObserver> observers;

	
	public ShapeList() {
		super();
		observers = new LinkedList<ShapeListObserver>();
	}
	
	public ShapeList(ShapeList x){
		observers = new LinkedList<ShapeListObserver>();
		for(PQShape temp : x)
		{
			try{
				this.add(0, temp.getDeepCopy());
			}
			catch(Exception ex){
				ex.printStackTrace();
			}
		}
		//this.add(x.getCurrentShape());
		for(ShapeListObserver y : x.getObservers())
		{
			observers.add(y);
		}
	}
	
	public PQShape getCurrentShape() {
		return currentShape;
	}
	
	public void setCurrentShape(PQShape p) {
		currentShape = p;
	}
	
	public void update() {
		for(ShapeListObserver o : observers) {
			o.update(this);
		}
	}
	
	public void clear() {
		CanvasWindow currWin = ((CanvasWindow)CanvasManager.getInst().getSelectedFrame());
		try{
			currWin.getUndoStack().push(currWin.getShapeList().getDeepCopy());
		}
		catch(Exception ex){
			System.out.println("Error in copy");
		}
		super.clear();
		currWin.getRedoStack().clear();
		currentShape = null;
		update();
	}
	
	public void addObserver(ShapeListObserver o) {
		if(observers == null)
		{
			observers = new LinkedList<ShapeListObserver>();
		}
		observers.add(o);
	}
	
	public LinkedList<ShapeListObserver> getObservers()
	{
		return observers;
	}
	
	public ShapeList getDeepCopy()throws Exception {
		ObjectOutputStream oos = null;
	    ObjectInputStream ois = null;
	    try
	    {
	       ByteArrayOutputStream bos = new ByteArrayOutputStream();
	       oos = new ObjectOutputStream(bos);
	       oos.writeObject(this);
	       oos.flush();
	       ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
	       ois = new ObjectInputStream(bin);
	       ShapeList x = (ShapeList)ois.readObject();
	       for(ShapeListObserver y : this.getObservers())
			{
				x.addObserver(y);
			}
	       return x;
	    }
	    catch(Exception e)
	    {
	       System.out.println("Exception in ObjectCloner = " + e);
	       throw(e);
	    }
	    finally
	    {
	       oos.close();
	       ois.close();
	    }
	}
	
	// This method allows reAddConnections to get a specific shape based on id.
	public Connectable getShape(Integer id) {
		Connectable c = null;
		
		for(PQShape x : this) {
			if(x.getShapeId() == id) {
				c = (Connectable) x;
				break;
			}
		}
		return c;
	}
}
